package com.example.normaldemo.numberView;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;

import androidx.annotation.RequiresApi;
import androidx.appcompat.widget.AppCompatEditText;

import com.example.normaldemo.R;

import java.math.BigDecimal;
import java.text.DecimalFormat;

public class NumberInputText extends AppCompatEditText implements TextWatcher {

    private Paint mPaint;
    /**
     * 边框样式
     */
    private static final String STYLE_RECT = "rectangle";//矩形
    private static final String STYLE_ROUND_RECT = "roundRect";//圆角矩形
    private static final String STYLE_HALF_RECT = "halfRect";//半矩形
    private static final String STYLE_ANIMATOR = "animator";//动画特效

    private static final int DEFAULT_ROUND_RADIUS = 20;//圆角矩形圆角度
    private static final int ANIMATOR_TIME = 200;//动画时间
    private static final int DEFAULT_FOCUSED_STROKE_WIDTH = 8;//获取到焦点的边框宽
    private static final int DEFAULT_UNFOCUSED_STROKE_WIDTH = 4;//未获取焦点的边框宽

    //步长 只考虑（1 2 5）三种不同精度的情况
    private static final float POINTER_STEP = 0.05f;
    private static final int POINTER_PRECISION = 2;
    private static final float MAX_VALUE = 500;

    //输入精度
    private int mInputPrecision;
    //输入步长
    private float mInputStep;
    //输入控制的最大值
    private float mMaxValue;

    //输入框边框颜色
    private int edit_border_color;
    private static final int DEFAULT_STYLE_COLOR = Color.RED;//边框默认颜色
    private String edit_border_style = "";

    public NumberInputText(Context context) {
        this(context, null);
    }

    public NumberInputText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public NumberInputText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.NumberInputText,
                0, 0);
        setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
        mInputPrecision = typedArray.getInteger(R.styleable.NumberInputText_input_precision, POINTER_PRECISION);
        mInputStep = typedArray.getFloat(R.styleable.NumberInputText_input_step, POINTER_STEP);
        mMaxValue = typedArray.getFloat(R.styleable.NumberInputText_input_max_value, MAX_VALUE);
        //输入框边框颜色
        edit_border_color = typedArray.getColor(R.styleable.NumberInputText_border_color, DEFAULT_STYLE_COLOR);
        typedArray.recycle();

        //抗锯齿和位图滤波
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        edit_border_style = STYLE_RECT;
        this.setFilters(new InputFilter[]{new PointFilter(mInputPrecision, mMaxValue)});
        this.addTextChangedListener(this);
    }

    /**
     * textWatcher事件监听
     */
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
        if (null == charSequence || TextUtils.isEmpty(charSequence.toString())) return;

        float mid = Float.valueOf(charSequence.toString());

        //在最后一位是小数点和可以被步长整除的情况下 不做任何处理
        if (mod(charSequence.toString(), String.valueOf(mInputStep)) || charSequence.toString().endsWith(".")) {
            return;
        }

        //最后的根据步长 计算而得的最终值
        double end = 0.0f;

        //在这里判断哪种情况需要验证（在精度的前一位开始判断有效性）
        //没有小数点的情况
        if (!charSequence.toString().contains(".")) {
            //没有小数点的情况下 只有精度为1的情况需要判断
            if (mInputPrecision <= 1) {
                end = (((int) (mid / mInputStep)) + 1) * mInputStep;
                end = (end > mMaxValue) ? mMaxValue : end;
            } else {
                return;
            }
        } else {
            //包含小数点的情况

            //小数点的位置
            int dotIndex = charSequence.toString().indexOf(".");

            //拿到当前的精度
            int currentPrecision = charSequence.toString().length() - dotIndex - 1;

            if (currentPrecision >= mInputPrecision - 1) {
                //包含小数点的情况 只有在精度的前一位需要判断
                end = (((int) (mid / mInputStep)) + 1) * mInputStep;
                end = (end > mMaxValue) ? mMaxValue : end;
            } else {
                return;
            }
        }
        this.setText(formatByPrecision(end));
        this.setSelection(this.getText().toString().length());
    }

    @Override
    public void afterTextChanged(Editable editable) {
    }

    /**
     * 对浮点数的取余运算
     */
    private boolean mod(String m, String n) {
        BigDecimal input = new BigDecimal(m);
        BigDecimal input2 = new BigDecimal(n);

        BigDecimal result = input.divide(input2, mInputPrecision, BigDecimal.ROUND_HALF_DOWN); //倍数
        //判断是否能整除
        if (new BigDecimal(result.intValue()).compareTo(result) == 0) {
            return true;
        }
        return false;
    }

    /**
     * 根据精度对数据格式化
     *
     * @param source 原始数据
     * @return 返回格式化后指定精度的数据
     */
    private String formatByPrecision(double source) {
        StringBuilder builder = new StringBuilder("0.");
        for (int i = 0; i < mInputPrecision; i++) {
            builder.append("0");
        }
        DecimalFormat decimalFormat = new DecimalFormat(builder.toString());//构造方法的字符格式这里如果小数不足2位,会以0补足.
        return decimalFormat.format(source);
    }

    /**
     * 绘制输入框外层边框
     *
     * @param canvas
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPaint.setStyle(Paint.Style.STROKE);

        //使用自定义颜色。如未定义，则使用默认颜色
        if (edit_border_color != -1) {
            mPaint.setColor(edit_border_color);
        } else {
            mPaint.setColor(DEFAULT_STYLE_COLOR);
        }

        //控件获取焦点时，加粗边框
        if (isFocused()) {
            mPaint.setStrokeWidth(DEFAULT_FOCUSED_STROKE_WIDTH);
        } else {
            mPaint.setStrokeWidth(DEFAULT_UNFOCUSED_STROKE_WIDTH);
        }

        //绘制边框
        drawBorder(canvas);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    private void drawBorder(Canvas canvas) {
        int width = getWidth();
        int height = getHeight();

        switch (edit_border_style) {
            //矩形样式
            case STYLE_RECT:
                setBackground(null);
                canvas.drawRect(0, 0, width, height, mPaint);
                break;

            //圆角矩形样式
            case STYLE_ROUND_RECT:
                setBackground(null);
                float roundRectLineWidth = 0;
                if (isFocused()) {
                    roundRectLineWidth = DEFAULT_FOCUSED_STROKE_WIDTH / 2;
                } else {
                    roundRectLineWidth = DEFAULT_UNFOCUSED_STROKE_WIDTH / 2;
                }
                mPaint.setStrokeWidth(roundRectLineWidth);
                if (Build.VERSION.SDK_INT >= 21) {
                    canvas.drawRoundRect(
                            roundRectLineWidth / 2, roundRectLineWidth / 2, width - roundRectLineWidth / 2, height - roundRectLineWidth / 2,
                            DEFAULT_ROUND_RADIUS, DEFAULT_ROUND_RADIUS,
                            mPaint);
                } else {
                    canvas.drawRoundRect(
                            new RectF(roundRectLineWidth / 2, roundRectLineWidth / 2, width - roundRectLineWidth / 2, height - roundRectLineWidth / 2),
                            DEFAULT_ROUND_RADIUS, DEFAULT_ROUND_RADIUS,
                            mPaint);
                }
                break;

            //半矩形样式
            case STYLE_HALF_RECT:
                setBackground(null);
                canvas.drawLine(0, height, width, height, mPaint);
                canvas.drawLine(0, height / 2, 0, height, mPaint);
                canvas.drawLine(width, height / 2, width, height, mPaint);
                break;

            //动画特效样式
            case STYLE_ANIMATOR:
//                setBackground(null);
//                if (isAnimatorRunning) {
//                    canvas.drawLine(width / 2 - mAnimatorProgress, height, width / 2 + mAnimatorProgress, height, mPaint);
//                    if (mAnimatorProgress == width / 2) {
//                        isAnimatorRunning = false;
//                    }
//                } else {
//                    canvas.drawLine(0, height, width, height, mPaint);
//                }
                break;
            default:
                break;
        }
    }
}
